package com.blog.configuration;

import java.util.concurrent.Callable;

import com.github.benmanes.caffeine.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.support.AbstractValueAdaptingCache;
import org.springframework.stereotype.Component;

/**
 * 本地缓存
 *
 * @author Joy
 * @date 2020-12-26
 */
@Component
public class LocalCache extends AbstractValueAdaptingCache{

    private static final Logger LOG = LoggerFactory.getLogger(LocalCache.class);

    public static final String NAME = "LocalCache";

    @Autowired
    private Cache<Object, Object> l1;

    public LocalCache(boolean allowNullValues) {
        super(allowNullValues);
    }

    public LocalCache() {
        super(true);
    }

    @Override
    protected Object lookup(Object key) {
        LOG.debug("[LocalCache.lookup}key:{}", key);
        return l1.getIfPresent(key);
    }

    @Override
    public String getName() {
        LOG.debug("[LocalCache.getName]{}", NAME);
        return NAME;
    }

    @Override
    public Object getNativeCache() {
        return this;
    }

    @Override
    public <T> T get(Object key, Callable<T> valueLoader) {
        LOG.debug("[LocalCache.get]key:{}, valueLoader:{}", key, valueLoader);
        Object value = lookup(key);
        LOG.debug("[LocalCache.get]key:{}, value:{}", key, value);
        if (value != null) {
            return (T)value;
        }
        try {
            T callValue = valueLoader.call();
            if (callValue != null) {
                put(key, callValue);
                value = callValue;
            }
        } catch (Exception e) {
            LOG.error("occur error", e);
        }
        LOG.debug("[LocalCache.get]key:{}, value:{}", key, value);
        return (T)value;
    }

    @Override
    public void put(Object key, Object value) {
        LOG.debug("[LocalCache.put]key:{}, value:{}", key, value);
        l1.put(key.toString(), value);
    }

    @Override
    public ValueWrapper putIfAbsent(Object key, Object value) {
        LOG.debug("[LocalCache.putIfAbsent]key:{}, value:{}", key, value);
        Object presentValue = l1.getIfPresent(key);
        if (presentValue != null) {
            return toValueWrapper(presentValue);
        }
        put(key, value);
        return toValueWrapper(value);
    }

    @Override
    public void evict(Object key) {
        LOG.debug("[LocalCache.evict]key:{}", key);
        l1.invalidate(key.toString());
    }

    @Override
    public void clear() {
        l1.invalidateAll();
    }
}
